home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume4 / vis < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  14.6 KB

  1. Path: xanth!mcnc!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
  2. From: george@rebel.UUCP (George M. Sipe)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i120: make any command screen oriented
  5. Message-ID: <48343@rebel.UUCP>
  6. Date: 11 Oct 88 02:20:38 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: george@rebel.UUCP (George M. Sipe)
  9. Organization: Tolerant Systems, Atlanta GA
  10. Lines: 500
  11. Approved: allbery@ncoast.UUCP
  12.  
  13. Posting-number: Volume 4, Issue 120
  14. Submitted-by: "George M. Sipe" <george@rebel.UUCP>
  15. Archive-name: vis
  16.  
  17. #! /bin/sh
  18. # This is a shell archive, meaning:
  19. # 1. Remove everything above the #! /bin/sh line.
  20. # 2. Save the resulting text in a file.
  21. # 3. Execute the file with /bin/sh (not csh) to create:
  22. #    README
  23. #    Makefile
  24. #    vis.man
  25. #    vis.c
  26. # This archive created: Fri Jul 22 14:37:25 1988
  27. export PATH; PATH=/bin:/usr/bin:$PATH
  28. if test -f 'README'
  29. then
  30.     echo shar: "will not over-write existing file 'README'"
  31. else
  32. sed 's/^X//' << \SHAR_EOF > 'README'
  33. XVis repeatedly executes a specified command and refreshes the display
  34. Xof its output on the screen.  This has the effect of making any
  35. Xnormally non-screen oriented command into a screen oriented one.
  36. X
  37. XThe first line on the output screen is reserved for vis status and will
  38. Xcontain the command on the left side with the current execution count
  39. Xon the right side.  If command is too long to fit, vis will truncate it
  40. Xin the status line and append an ellipsis ("...").
  41. X
  42. XThe output of the command normally begins on the third line and
  43. Xcontinues to the end of the screen.  Lines which can not fit will be
  44. Xdiscarded.  When this occurs, vis will automatically place the output
  45. Xof following passes starting on line two in order to maximize the
  46. Xamount of displayed information.
  47. X
  48. XSee the manual page for a complete information.
  49. X
  50. X
  51. X     Copyright (c) 1988 by George M. Sipe.  All rights reserved.
  52. X
  53. XThis software may only be redistributed without fee and without any
  54. Xother form of monetary gain (including sold, rented, leased, or
  55. Xtraded), unless the express written permission of the copyright holder
  56. Xis obtained in advance.
  57. X
  58. XThis copyright notice must be reproduced in its entirety on all copies
  59. Xof this software.  Further, acknowledgment of the authorship of this
  60. Xsoftware must not be removed from its current or derived
  61. Xdocumentation.
  62. X
  63. XNo expressed or implied warranty is made for this software.  No party
  64. Xconnected with this software assumes any liability or responsibility
  65. Xfor its use, the correctness of its operation, or its fitness for any
  66. Xpurpose.
  67. X
  68. XAny distributor of copies of this software shall grant the recipient
  69. Xpermission for further redistribution as permitted by this notice.
  70. X
  71. XPermission is hereby granted to copy, reproduce, redistribute and
  72. Xotherwise use this software as long as the conditions above are
  73. Xstrictly adhered to.
  74. X
  75. XNOTE:    This software was originally written by Dan Heller
  76. X    (argv@sri-spam.arpa) and enhanced / generalized by
  77. X    George M.  Sipe (rebel!george) to the point where Dan
  78. X    would no longer recoginze it.  No copyright notices
  79. X    were embodied in the original net distribution.
  80. SHAR_EOF
  81. fi
  82. if test -f 'Makefile'
  83. then
  84.     echo shar: "will not over-write existing file 'Makefile'"
  85. else
  86. sed 's/^X//' << \SHAR_EOF > 'Makefile'
  87. X# Makefile for:  vis - repeatedly run command, refreshing screen
  88. X
  89. XDEFINES        = -DBSD
  90. XCFLAGS        = -O $(DEFINES)
  91. XLIBS        = -lcurses -ltermcap
  92. XROFF        = nroff
  93. XRFLAGS        = -man
  94. XLDFLAGS        = -s
  95. XDESTBIN        = ${HOME}
  96. XDESTMAN        = ${HOME}
  97. XDESTCAT        = ${HOME}
  98. XDESTOWN        = root
  99. XDESTGRP        = staff
  100. XSHELL        = /bin/sh
  101. XMAKEFILE    = Makefile
  102. XPROGRAM        = vis
  103. XMANPAGES    = vis.man
  104. XCATPAGES    = vis.cat
  105. XSRCS        = vis.c
  106. XOBJS        = vis.o
  107. X
  108. X.man.cat:
  109. X        $(ROFF) $(RFLAGS) $< > $@
  110. X
  111. X.SUFFIXES:    .man .cat
  112. X
  113. X# Compile and load the program and format its manual pages.
  114. Xall:        $(PROGRAM) $(CATPAGES)
  115. X
  116. X$(PROGRAM):    $(OBJS)
  117. X        $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
  118. X
  119. X# Run lint on source files, put results on standard output.
  120. Xlint:
  121. X        lint -u $(DEFINES) $(SRCS)
  122. X
  123. X# Create a tags file for use by a source code editor.
  124. Xtags:        $(SRCS)
  125. X        ctags $(SRCS)
  126. X
  127. X# Edit the makefile and regenerate the dependency information.
  128. Xdepend:
  129. X        mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DESTBIN=$(DESTBIN)
  130. X
  131. X# Print an index of functions on standard output.
  132. Xindex:
  133. X        ctags -wx $(SRCS)
  134. X
  135. X# Print source code files on standard output.
  136. Xprint:
  137. X        lpr -p $(SRCS) $(MANPAGES)
  138. X
  139. X# Compile and load the program, format manual pages, and move them
  140. X# to their destination directories.
  141. Xinstall:    $(PROGRAM) $(CATPAGES)
  142. X        cp $(PROGRAM) $(DESTBIN)
  143. X        chmod 755 $(DESTBIN)/$(PROGRAM)
  144. X        chown $(DESTOWN) $(DESTBIN)/$(PROGRAM)
  145. X        chgrp $(DESTGRP) $(DESTBIN)/$(PROGRAM)
  146. X        -for manpage in $(MANPAGES); do \
  147. X            basepage=`basename $$manpage .man`; \
  148. X            cp $$basepage.man $(DESTMAN)/$$basepage.l; \
  149. X            chmod 644 $(DESTMAN)/$$basepage.l; \
  150. X            chown $(DESTOWN) $(DESTMAN)/$$basepage.l; \
  151. X            chgrp $(DESTGRP) $(DESTMAN)/$$basepage.l; \
  152. X            cp $$basepage.cat $(DESTCAT)/$$basepage.l; \
  153. X            chmod 644 $(DESTCAT)/$$basepage.l; \
  154. X            chown $(DESTOWN) $(DESTCAT)/$$basepage.l; \
  155. X            chgrp $(DESTGRP) $(DESTCAT)/$$basepage.l; \
  156. X        done
  157. X
  158. X# Remove the program and its formatted manual pages from their
  159. X# destination directories.
  160. Xuninstall:
  161. X        rm -f $(DESTBIN)/$(PROGRAM)
  162. X        -for manpage in $(MANPAGES); do \
  163. X            basepage=`basename $$manpage .man`; \
  164. X            rm -f $(DESTMAN)/$$basepage.l; \
  165. X            rm -f $(DESTCAT)/$$basepage.l; \
  166. X        done
  167. X
  168. X# Remove all target and intermediate files.
  169. Xclean:
  170. X        -rm -f $(PROGRAM) $(CATPAGES) $(OBJS)
  171. X        -rm -f core a.out made *.o
  172. SHAR_EOF
  173. fi
  174. if test -f 'vis.man'
  175. then
  176.     echo shar: "will not over-write existing file 'vis.man'"
  177. else
  178. sed 's/^X//' << \SHAR_EOF > 'vis.man'
  179. X.TH VIS l "21 July 1988"
  180. X.SH NAME
  181. Xvis \- repeatedly run command, refreshing screen
  182. X.SH SYNTAX
  183. X.B vis "[-d delay] [-f] command [args]"
  184. X.SH DESCRIPTION
  185. X.I Vis
  186. Xrepeatedly executes a specified
  187. X.B command
  188. Xand refreshes the display of its output on the screen.  This has the
  189. Xeffect of making any normally non-screen oriented command into a screen
  190. Xoriented one.
  191. X.PP
  192. X.B Command
  193. Xmay represent multiple commands by enclosing them in quotes and
  194. Xseparating them by ``;''.  Similarly, commands may be piped together by
  195. Xenclosing them in quotes and separating them by ``|''.  The single or
  196. Xdouble quotes around such a compound command are necessary to escape
  197. Xprocessing from the shell.
  198. X.PP
  199. XThe first line on the output screen is reserved for
  200. X.I vis
  201. Xstatus and will contain the
  202. X.B command
  203. Xon the left side with the current execution count on the right side.  If
  204. X.B command
  205. Xis too long to fit,
  206. X.I vis
  207. Xwill truncate it in the status line and append an ellipsis ("...").
  208. X.PP
  209. XThe output of the command normally begins on the third line and
  210. Xcontinues to the end of the screen.  Lines which can not fit will be
  211. Xdiscarded.  When this occurs,
  212. X.I vis
  213. Xwill automatically place the output of following passes starting on line
  214. Xtwo in order to maximize the amount of displayed information.
  215. X.PP
  216. XThe following switches may be specified if desired:
  217. X.TP 10
  218. X.B "-d delay"
  219. Xspecifies a non-default delay of
  220. X.B delay
  221. Xseconds.  Normally
  222. X.I vis
  223. Xwill delay for 15 seconds between command re-executions.  If a
  224. Xnon-default delay is specified, the
  225. X.I vis
  226. Xstatus line will also include the delay interval centered within it
  227. X(unless that would cause it to overwrite a long command, in which case
  228. Xit will be centered between the end of the command and the execution
  229. Xcount).
  230. X.TP
  231. X.B -f
  232. X.I Vis
  233. Xwill automatically terminate if
  234. X.B command
  235. Xreturns a non-zero status.  The
  236. X.B -f
  237. Xflag forces
  238. X.I vis
  239. Xto continue.  When
  240. X.B -f
  241. Xis specified,
  242. X.I vis
  243. Xwill not terminate and will instead precede the execution count in the
  244. X.I vis
  245. Xstatus line by a ``!'' flag whenever a non-zero status has been returned
  246. Xby
  247. X.B command .
  248. X.SH EXAMPLES
  249. Xvis ps
  250. X.IP "" 5
  251. XContinually display the status of processes on the system (up to 23
  252. Xlines).
  253. X.PP
  254. Xvis -d 60 'who ; echo ""; df'
  255. X.IP "" 5
  256. XDisplay the system users and disk usage statistics every 60 seconds.
  257. XSeparate the two with a blank line.
  258. X.SH "SEE ALSO"
  259. XUser Commands (1):  sh, csh
  260. X.SH DIAGNOSTICS
  261. XIf
  262. X.B command
  263. Xreturns a non-zero status and
  264. X.B -f
  265. Xhas not been specified to
  266. X.I vis ,
  267. X.I vis
  268. Xwill terminate and return that status.
  269. X.SH AUTHOR
  270. XOriginally written by Dan Heller (argv@sri-spam.arpa).
  271. X.PP
  272. XIt has been substantially enhanced and generalized by George M. Sipe
  273. X(currently - 7/88, at rebel!george) to the point where Dan would no
  274. Xlonger recognize it.
  275. SHAR_EOF
  276. fi
  277. if test -f 'vis.c'
  278. then
  279.     echo shar: "will not over-write existing file 'vis.c'"
  280. else
  281. sed 's/^X//' << \SHAR_EOF > 'vis.c'
  282. X/*   Copyright (c) 1988 by George M. Sipe.  All rights reserved.
  283. X
  284. XThis software may only be redistributed without fee and without any
  285. Xother form of monetary gain (including sold, rented, leased, or
  286. Xtraded), unless the express written permission of the copyright holder
  287. Xis obtained in advance.
  288. X
  289. XThis copyright notice must be reproduced in its entirety on all copies
  290. Xof this software.  Further, acknowledgment of the authorship of this
  291. Xsoftware must not be removed from its current or derived
  292. Xdocumentation.
  293. X
  294. XNo expressed or implied warranty is made for this software.  No party
  295. Xconnected with this software assumes any liability or responsibility
  296. Xfor its use, the correctness of its operation, or its fitness for any
  297. Xpurpose.
  298. X
  299. XAny distributor of copies of this software shall grant the recipient
  300. Xpermission for further redistribution as permitted by this notice.
  301. X
  302. XPermission is hereby granted to copy, reproduce, redistribute and
  303. Xotherwise use this software as long as the conditions above are
  304. Xstrictly adhered to.
  305. X
  306. X    NOTE:  This software was originally written by Dan Heller
  307. X    (argv@sri-spam.arpa) and enhanced / generalized by George M.
  308. X    Sipe (rebel!george) to the point where Dan would no longer
  309. X    recoginze it.  No copyright notices were embodied in the
  310. X    original net distribution.
  311. X*/
  312. X
  313. X#include <stdio.h>
  314. X#include <curses.h>
  315. X#include <signal.h>
  316. X#include <sys/types.h>
  317. X
  318. X#ifndef    DELAY
  319. X#define    DELAY    15        /* default delay, if not otherwise set */
  320. X#endif    DELAY
  321. X#ifndef    BASELINE
  322. X#define    BASELINE 2        /* default line number for output */
  323. X#endif    BASELINE
  324. X
  325. X#define max(a,b)         (a < b ? b : a)
  326. X#define equal(str1,str2)    !strcmp(str1, str2)
  327. X
  328. X#define pinput             fildes[0]
  329. X#define poutput            fildes[1]
  330. X
  331. X#ifdef    BSD
  332. X#include <sys/wait.h>
  333. Xextern char *index();
  334. Xextern time_t time();
  335. Xextern int exit();
  336. Xextern int _exit();
  337. Xextern int perror();
  338. Xextern int sleep();
  339. X#else
  340. Xunion wait {
  341. X    int w_status;
  342. X};
  343. X#define    vfork()        fork()                /* fork on non-BSD */
  344. X#define    dup2(from,to)    close(to); (void) dup(from)    /* good enough here */
  345. X#define    index(str,chr)    strchr(str,chr)            /* strchr on non-BSD */
  346. Xextern char *strchr();
  347. Xextern long time();
  348. Xextern void exit();
  349. Xextern void _exit();
  350. Xextern void perror();
  351. Xextern unsigned int sleep();
  352. X#endif    BSD
  353. X
  354. Xextern int optind;
  355. Xextern char *optarg;
  356. X
  357. Xlong wait_delay = DELAY;    /* delay interval */
  358. Xint force = 0;            /* true to force continued execution */
  359. Xint needshell = 0;        /* non-zero if subshell needed */
  360. X
  361. X/* create command line string for display */
  362. Xstatic char *command(argc, argv)
  363. Xint argc;
  364. Xchar **argv;
  365. X{
  366. X    static char string[255];
  367. X    int count = 0;
  368. X    char *cp = string;
  369. X
  370. X    do {
  371. X        (void) sprintf(cp, "%s ", argv[count]);
  372. X        cp += strlen(cp);
  373. X        needshell |= (int) index(argv[count], '|');
  374. X        needshell |= (int) index(argv[count], ';');
  375. X    } while (++count < argc);
  376. X    *--cp = '\000';
  377. X    return (string);
  378. X}
  379. X
  380. X/* all done, cleanup and exit */
  381. Xstatic int terminate(cause)
  382. X{
  383. X#ifdef    BSD
  384. X    (void) sigsetmask(-1);
  385. X#endif
  386. X    move(LINES - 1, 0);
  387. X    clrtoeol();
  388. X    echo();
  389. X    refresh();
  390. X    endwin();
  391. X    exit(cause);
  392. X}
  393. X
  394. Xint main(argc, argv)
  395. Xint argc;
  396. Xchar **argv;
  397. X{
  398. X    register int curline;
  399. X    register int iteration = 0;
  400. X    register int c;
  401. X    int sw;
  402. X    int badsw = 0;
  403. X    int baseline = BASELINE;
  404. X    long nextcycle;
  405. X    long curtime;
  406. X    long delta;
  407. X    int fildes[2];
  408. X    int pid;
  409. X    union wait status;
  410. X    char *cmd = argv[0];
  411. X    char *shcmd[4];
  412. X    FILE *fp;
  413. X
  414. X    (void) signal(SIGQUIT, terminate);    /* exit when requested */
  415. X    (void) signal(SIGINT, terminate);    /* exit when requested */
  416. X    (void) signal(SIGPIPE, SIG_IGN);    /* when output > screen size */
  417. X
  418. X    while ((sw = getopt (argc, argv, "d:f")) != EOF)
  419. X        switch (sw) {
  420. X            case 'f':
  421. X                force = !force;
  422. X                break;
  423. X            case 'd':
  424. X                wait_delay = atoi(optarg);
  425. X                if (wait_delay < 1) wait_delay = 1;
  426. X                break;
  427. X            case '?':
  428. X            default:
  429. X                badsw = 1;
  430. X                break;
  431. X        }
  432. X    argv = &argv[optind];
  433. X    argc -= optind;
  434. X    if (badsw || argc < 1) {
  435. X        (void) fprintf(stderr,
  436. X            "Usage: %s [-d delay] [-f] command [args]\n", cmd);
  437. X        exit (-1);
  438. X    }
  439. X    initscr();
  440. X    cmd = command(argc, argv);
  441. X    if (needshell != 0) {
  442. X        shcmd[0] = "sh";
  443. X        shcmd[1] = "-c";
  444. X        shcmd[2] = cmd;
  445. X        shcmd[3] = (char *) 0;
  446. X    }
  447. X    if (wait_delay != DELAY) {
  448. X        if (strlen(cmd) > COLS-39)
  449. X            (void) sprintf(cmd, "%.*s...", COLS-42, cmd);
  450. X        mvprintw(0, max((COLS-11)/2, strlen(cmd)+15), "Delay:  %d",
  451. X            wait_delay);
  452. X    } else if (strlen(cmd) > COLS-21)
  453. X        (void) sprintf(cmd, "%.*s...", COLS-24, cmd);
  454. X    mvprintw(0, 0, "Command:  %s", cmd);
  455. X    noecho();            /* don't let typing ruin our painting */
  456. X    nextcycle = time(0) + wait_delay;
  457. X    while (1) {
  458. X        mvprintw(0, COLS - 10, "Exec:  %d", ++iteration);
  459. X        if (iteration == 1) refresh();
  460. X        (void) pipe(fildes);
  461. X        /* fork and exec redirecting stdout thru pipe to curses */
  462. X        if (!(pid = vfork())) {
  463. X            (void) dup2(poutput, 1);
  464. X            (void) dup2(poutput, 2);
  465. X            (void) close(pinput);
  466. X            if (needshell == 0) (void) execvp(*argv, argv);
  467. X            else (void) execv("/bin/sh", shcmd);
  468. X            perror(*argv);
  469. X            _exit(-1);
  470. X        }
  471. X        if (pid == -1) terminate(-2);
  472. X        if (!(fp = fdopen(pinput, "r"))) terminate(-3);
  473. X        (void) close(poutput);
  474. X        curline = baseline;
  475. X        move(curline, 0);
  476. X        /* read the command's output */
  477. X        while ((c = getc(fp)) != EOF && !ferror(fp) && curline < LINES)
  478. X                if (c == '\n') {
  479. X                    clrtoeol();
  480. X                    move(++curline, 0);
  481. X                }
  482. X                else addch(c);
  483. X        if (ferror(fp)) terminate(-4);
  484. X        if (baseline > 1 && curline == LINES && c != EOF)
  485. X            --baseline;
  486. X        /* we've found the end of file, thus, the end of exec */
  487. X        (void) fclose(fp);
  488. X        clrtobot();
  489. X        move(LINES - 1, 0);
  490. X        refresh();
  491. X        (void) wait(&status);    /* wait for child to terminate */
  492. X        /* if child didn't terminate properly, w_status will != 0 */
  493. X        if (status.w_status) {
  494. X            mvprintw(0, COLS - 12, "!");
  495. X            if (!force) terminate(status.w_status);
  496. X        }
  497. X        curtime = time(0);
  498. X        delta = nextcycle - curtime;
  499. X        if (delta > 0) {
  500. X            nextcycle = curtime + delta + wait_delay;
  501. X            (void) sleep((unsigned) delta);
  502. X        } else nextcycle = curtime + wait_delay;
  503. X    }
  504. X}
  505. SHAR_EOF
  506. fi
  507. exit 0
  508. #    End of shell archive
  509. -- 
  510. George M. Sipe,        Phone: (404) 662-1533
  511. Tolerant Systems, 6961 Peachtree Industrial, Norcross, GA  30071
  512. UUCP: ...!{decvax,hplabs,linus,rutgers,seismo}!gatech!rebel!george
  513.